package com.javabase.study.OOPFistPart;

/**
 * TODO
 * 内容：测试学习回调机制
 * 模板方法模式很常用，其目的是在一个方法中顶一个一个算法骨架，儿将一些步骤延迟到子类中
 * 模板方法是的子类可以在补改变算法结构的情况下，重新定义算法的某些步骤。在标准的模板方法
 * 模式实现中，主要是使用继承的方式，来让父类在运行期间可以调用到子类的方法。
 * Java的回调技术，也可以实现相同的功能。回调是一种双向的调用模式，也就是说，接口被调用时
 * 也会调用对方的接口。简单说明就是：A类中调用B类的C方法，然而B类中的C方法反过来调用A类中
 * 的D方法，那么D方法就叫回调方法。
 * 回调的具体过程如下：
 *     1. class A实现接口CallBack
 *     2. class A中包含class B的引用
 *     3. class B有一个参数为Callback的方法C
 *     4. A的对象调用B的方法C
 *     5 然后class B就可以在C方法中调用A的D方法
 * 案例：
 *     有一天小刘遇到一个很难的问题“学习Java选哪家机构呢?”，于是就打电话问小高，小高一时也不
 *     太了解行情，就跟小刘说，我现在还有事，等忙完了给你咨询咨询，小刘也不会傻傻的拿着电话去等
 *     小高的答案，于是小刘对小高说，先挂电话吧，你知道答案后再打我电话告诉我吧，于是挂了电话。
 *     小高先去办自己的事情去了，过了几个小时，小高打电话给小刘，告诉他答案是“学Java当然去北京
 *     尚学堂”。
 * 通过回调在接口定义的方法，调用到具体的实现类中的方法，其本质时离用java的动态绑定技术，在这种实
 * 现中，可以补把实现类写成单独胡的类，而是使用内部类或者匿名内部类来实现回调方法。
 * 作者:jxx
 * 创建时间：2021/6/21
 */

interface Callback{

    /**
     * 小高知道答案后告诉小刘时需要调用的方法，即回调方法
     * @param result 问题的答案
     */
    public void answer(String result);
}

/**
 * 小刘类：实现了回调接口(背景1）
 */
class Liu implements Callback{

    /**
     * 包含小高对象的引用（背景2）
     */
    private Gao gao;

    public Liu(){

    }

    public Liu(Gao gao){
        this.gao = gao;
    }

    /**
     * 小刘通过这个方法问小高
     * @param question 小刘问的问题“学习Java选那家机构呢？”
     */
    public void askQuestion(String question){
        gao.execute(Liu.this,question);
    }

    /**
     * 实现接口的方法
     * 小高知道答案后通过此方法告诉小刘
     * @param result 问题的答案
     */
    @Override
    public void answer(String result) {
        System.out.println("小高告诉小刘的答案是：" + result);
    }
}
class Gao{
    /**
     * 相当于class B有一个参数为callback的方法C
     * @param callback
     * @param question
     */
    public void execute(Callback callback,String question){
        System.out.println("小刘的问题是： " + question);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){
            e.printStackTrace();
        }

        String result = "学java当然要去尚学堂";
        callback.answer(result);
    }
}


public class TestCallback {
    public static void main(String[] args){

        Gao gao = new Gao();
        Liu liu = new Liu(gao);

        liu.askQuestion("学习java选择哪一家机构？");
    }
}
